#ifndef RTP_PARSE_SENDERREPORT_H
#define RTP_PARSE_SENDERREPORT_H

#include "rtp/Packet.h"
#include <vector>
#include <arpa/inet.h>
#include <algorithm>

/**
 * SR  --- SenderReport
 * 发送端定期向接收端报告发送端的统计信息(如发送包数、字节数)和时序关系(NTP时间戳、RTP时间戳)
 * 核心功能:
 *  1.时间同步
 *      通过 NTP 和 RTP 时间戳映射，实现多媒体同步
 *  2.往返时间(RTT)计算
 *      接收端利用SR和RR计算RTT '收到SR后，接收端记录收到时间，用返回的RR包中的DLRR字段，发送端就能算RTT'
 *      
 *  3.带宽估计和质量监控
 *      通过包计数和字节计数，接收端可以:
 *          计算发送速率
 *          检测网络拥塞
 *          调整接收缓冲区
 * 
 * 在实际系统中，SR 与 RR（Receiver Report）配合使用，共同构成了实时通信系统的监控和反馈机制，是保证音视频质量的关键技术基础。
 */

namespace Rtp {
    namespace Rtcp {
        class SenderReport {
        public:
            /** Struct for RTCP sender report */
            struct Header {
                uint32_t ssrc;
                // ntpSec 和ntpFrac 组成NTP Timestamp
                uint32_t ntpSec;  // 高32位 从1900年1月1日开始的秒数
                uint32_t ntpFrac; // 低32位 秒的小数部分 （精度约为200皮秒)
                uint32_t rtpTs;  // 与NTP时间戳对应的RTP时间戳
                uint32_t packetCount; // 从开始发送到现在的总包数
                uint32_t octetCount; // 从开始发送到现在的总字节数
            };

        public:
            static const size_t HeaderSize { 24 };
            static SenderReport* Parse(const uint8_t* data, size_t len);
        public:
            SenderReport() {
                this->header = reinterpret_cast<Header *>(this->raw);
            }

            explicit SenderReport(Header *header): header(header) {}

            explicit SenderReport(SenderReport* report):header(report->header) {}

            void Dump() const;
            size_t Serialize(uint8_t *buffer);
            size_t GetSize() const {
                return HeaderSize;
            }
            uint32_t GetSsrc() const {
                return uint32_t{ ntohl(this->header->ssrc) };
            }
            void SetSsrc(uint32_t ssrc) {
                this->header->ssrc = uint32_t{ htonl(ssrc) };
            } 

            uint32_t GetNtpSec() const {
                return uint32_t { ntohl(this->header->ntpSec) };
            }

            void SetNtpSec(uint32_t ntpSec) {
                this->header->ntpSec = uint32_t{ htonl(ntpSec) };
            }

            uint32_t GetNtpFrac() const {
                return uint32_t{ ntohl(this->header->ntpFrac) };
            }

            void SetNtpFrac( uint32_t ntpFrac) {
                this->header->ntpFrac = uint32_t{ htonl(ntpFrac) };
            }

            uint32_t GetRtpTs() const {
                return uint32_t{ ntohl(this->header->rtpTs) };
            }

            void SetRtpTs(uint32_t rtpTs) {
                this->header->rtpTs = uint32_t{ htonl(rtpTs) };
            }

            uint32_t GetPacketCount() const {
                return uint32_t{ ntohl(this->header->packetCount) };
            }

            void SetPacketCount(uint32_t packetCount) {
                this->header->packetCount = uint32_t{ htonl(packetCount) };
            } 

            uint32_t GetOctetCount() const {
                return uint32_t{ ntohl(this->header->octetCount) };
            }

            void SetOctetCount(uint32_t octetCount) {
                this->header->octetCount = uint32_t{ htonl(octetCount) };
            }

        private:
            Header* header { nullptr };
            uint8_t raw[HeaderSize] { 0 };
        };

        class SenderReportPacket: public Packet {
        public:
            using Iterator = std::vector<SenderReport*>::iterator; 
        public:
            static SenderReportPacket* Parse(const uint8_t* data, size_t len);
        public:
            SenderReportPacket():Packet(Type::SR) {}
            explicit SenderReportPacket(CommonHeader* commonHeader):Packet(commonHeader) {}

            ~SenderReportPacket() override {
                for (auto *report : this->reports) {
                    delete report;
                }
            }

            void AddReport(SenderReport *report) {
                this->reports.push_back(report);
            }

            void RemoveReport(SenderReport *report) {
                auto it = std::find(this->reports.begin(), this->reports.end(), report);
                if (it != this->reports.end()) {
                    this->reports.erase(it);
                }
            }

            Iterator begin() {
                return this->reports.begin();
            }

            Iterator End() {
                return this->reports.end();
            }
        public:
            void Dump() const override;
            size_t Serialize(uint8_t *buffer) const override;
            size_t GetCount() const override {
                return this->reports.size();
            }

            size_t GetSize() const override {
                size_t size { 0 };
                for (auto *report : this->reports) {
                    size += Packet::CommonHeaderSize;
                    size += report->GetSize();
                } 
                return size;
            }
        private:
            std::vector<SenderReport *> reports;
        };
    }
}


#endif